package com.yc.Testjvm;

import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.vm.VM;

/**
 * 一个观察对象内存分布的第三方工具包
 */
public class TestJOL {
    public static void main(String[] args) {
        TestJOL t = new TestJOL();
//        t.m1();
//        t.m2();
//        try {
//            m3();
//        } catch (InterruptedException e) {
//            throw new RuntimeException(e);
//        }

        try {
            t.m4();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public void m1() {
        System.out.println(VM.current().details());

        Object lock = new Object();
        System.out.println(ClassLayout.parseInstance(lock).toPrintable());
    }

    static Integer count = 0;

    /**
     * 有一个成员变量Integer count=0
     * 一百个线程，每个线程循环10000次，每次循环休眠1毫秒
     * 循环体内使用synchronized来保证同步，修改变量count++。
     * 最终count值为1000000
     */
    public void m2() {
//        TestJOL t = new TestJOL();

        //观察count对象
        System.out.println(ClassLayout.parseInstance(count).toPrintable());

        for (int i = 0; i < 100; i++) {
            new Thread(() -> TestJOL.add2()).start();
        }

        //等5秒
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("count=" + count);
        //再次观察count对象
        System.out.println(ClassLayout.parseInstance(count).toPrintable());

    }

    /**
     * 这个写法不对，这样最多只有100次抢锁（我希望有1000000次抢锁动过程）
     */
    public static synchronized void add() {
        for (int i = 0; i < 10000; i++) {
            count++;
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    static Object synchronizedLock = new Object();
    public static void add2() {
        for (int i = 0; i < 10000; i++) {
            synchronized (synchronizedLock) {
                count++;
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }

        }

    }

    /**
     * 无锁 —剧烈争夺—> 重量级锁 —等待10秒—> 无锁
     * 证明了：轻量级锁，重量级锁 在之后如果没有其他线程访问，锁会重新变成无锁状态
     * 如果还有竞争（后面还有人在等着），那么在前一个线程执行完，唤醒后面一个线程继续运行后，并不会改变锁动状态
     * @throws InterruptedException
     */
    public static void m3() throws InterruptedException {
        //观察count对象
        System.out.println(ClassLayout.parseInstance(synchronizedLock).toPrintable());

        Thread[] threads = new Thread[100];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 10000; j++) {
                    synchronized (synchronizedLock) {
                        count++;
                    }
                }
            });
            threads[i].start();
        }
        for (Thread thread : threads) {
            thread.join();
        }
        System.out.println(count);

        //观察count对象
        System.out.println(ClassLayout.parseInstance(synchronizedLock).toPrintable());

        //等10秒钟
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //观察count对象
        System.out.println(ClassLayout.parseInstance(synchronizedLock).toPrintable());

    }

    public void m4() throws InterruptedException {
        // 禁用偏向锁延迟
        System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        Object synchronizedLock = new Object();

        //观察count对象
        System.out.println(ClassLayout.parseInstance(synchronizedLock).toPrintable());

        Thread t = new Thread(() -> {
            synchronized (synchronizedLock) {
                System.out.println(ClassLayout.parseInstance(synchronizedLock).toPrintable());
            }
        });
        t.start();
        t.join();
        // 确保线程t1已经释放锁
        Thread.sleep(1000);

        // 再次打印对象头信息，此时锁仍然是偏向锁，偏向于线程t1
        System.out.println("After biased locking (Thread 1):");
        System.out.println(ClassLayout.parseInstance(synchronizedLock).toPrintable());


    }
}
